home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: delta / whiteline CD Series - delta.iso / tex / tools / dvi_300b / treiber / dvinadel.lzh / dvinadel / nadel.c < prev    next >
C/C++ Source or Header  |  1995-09-20  |  34KB  |  1,041 lines

  1. /*
  2.     Nadel-Druckertreiber für DVI
  3.  
  4.     Version 1.2
  5.     Copyright (c) Markus Kohm, 1995
  6.  
  7.     Diese Treiberbasisdatei kommt mit Nadeldruckern und
  8.     Tintenspritzern, die wie Nadeldrucker angesteuert werden,
  9.     von 8 bis 48 Nadeln (bzw. Düsen) zurecht.
  10.     Es wird lediglich eine Ansteuerungsdefinitionsdatei benötigt.
  11.     Ein Beispiel dafür liefert LQ850.C.
  12.  
  13.     Der Ausdruck wird über das Modul prt_base erledigt.
  14.     Es wird MiNTLIB PL 46 benötigt.
  15. */
  16.  
  17. #ifndef NADEL_C
  18. #define NADEL_C
  19.  
  20. #ifndef PRT_BASE_H
  21. # error "Diese Datei immer nur per #include verwenden (siehe dvi_prt.c)!"
  22. #endif
  23.  
  24. #include <ctype.h>
  25. #include <errno.h>
  26. #include <fcntl.h>
  27. #include <mintbind.h>
  28. #include <signal.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include "dvi_low.h"
  32.  
  33. #ifndef SHMGETBLK
  34. # define  SHMGETBLK (0x4d00)
  35. #endif
  36.  
  37. #if !defined( PORTRAIT ) && !defined( LANDSCAPE )
  38. # define PORTRAIT
  39. # define LANDSCAPE
  40. #endif
  41.  
  42. char EVERYSECONDBIT[128] = {
  43.   0x0, 0x1, 0x0, 0x1, 0x2, 0x3, 0x2, 0x3,
  44.   0x0, 0x1, 0x0, 0x1, 0x2, 0x3, 0x2, 0x3,
  45.   0x4, 0x5, 0x4, 0x5, 0x6, 0x7, 0x6, 0x7,
  46.   0x4, 0x5, 0x4, 0x5, 0x6, 0x7, 0x6, 0x7,
  47.  
  48.   0x0, 0x1, 0x0, 0x1, 0x2, 0x3, 0x2, 0x3,
  49.   0x0, 0x1, 0x0, 0x1, 0x2, 0x3, 0x2, 0x3,
  50.   0x4, 0x5, 0x4, 0x5, 0x6, 0x7, 0x6, 0x7,
  51.   0x4, 0x5, 0x4, 0x5, 0x6, 0x7, 0x6, 0x7,
  52.  
  53.   0x8, 0x9, 0x8, 0x9, 0xa, 0xb, 0xa, 0xb,
  54.   0x8, 0x9, 0x8, 0x9, 0xa, 0xb, 0xa, 0xb,
  55.   0xc, 0xd, 0xc, 0xd, 0xe, 0xf, 0xe, 0xf,
  56.   0xc, 0xd, 0xc, 0xd, 0xe, 0xf, 0xe, 0xf,
  57.  
  58.   0x8, 0x9, 0x8, 0x9, 0xa, 0xb, 0xa, 0xb,
  59.   0x8, 0x9, 0x8, 0x9, 0xa, 0xb, 0xa, 0xb,
  60.   0xc, 0xd, 0xc, 0xd, 0xe, 0xf, 0xe, 0xf,
  61.   0xc, 0xd, 0xc, 0xd, 0xe, 0xf, 0xe, 0xf
  62. };
  63.  
  64. #define EVENBITS(x) EVERYSECONDBIT[x/2]
  65. #define ODDBITS(x)  EVERYSECONDBIT[x&127]
  66.  
  67. #define WHICHNORMAL(n,x)  x
  68.  
  69. char DOUBLEBITS[16] = {
  70.   0x00, 0x03, 0x0c, 0x0f,
  71.   0x30, 0x33, 0x3c, 0x3f,
  72.   0xc0, 0xc3, 0xcc, 0xcf,
  73.   0xf0, 0xf3, 0xfc, 0xff };
  74.  
  75. #define DOUBLEFIRST(x)    (DOUBLEBITS[((x) >> 4) & 0x0f])
  76. #define DOUBLESECOND(x)   (DOUBLEBITS[(x) & 0x0f])
  77. #define WHICHDOUBLE(n,x)  (((n) == 0)? DOUBLEFIRST(x) : DOUBLESECOND(x))
  78.  
  79. char TRIPLEFIRSTBITS[8] = {
  80.   0x00, 0x03, 0x1c, 0x1f,
  81.   0xe0, 0xe3, 0xfc, 0xff };
  82. char TRIPLESECONDBITS[16] = {
  83.   0x00, 0x01, 0x0e, 0x0f,
  84.   0x70, 0x71, 0x7e, 0x7f,
  85.   0x80, 0x81, 0x8e, 0x8f,
  86.   0xf0, 0xf1, 0xfe, 0xff };
  87.  
  88. #define TRIPLEFIRST(x)    TRIPLEFIRSTBITS[(x >> 5) & 0x07]
  89. #define TRIPLESECOND(x)   TRIPLESECONDBITS[(x >> 2) & 0x0f]
  90. #define TRIPLETHIRD(x)    ((TRIPLEFIRSTBITS[x & 0x07] << 1) |\
  91.                            TRIPLEFIRSTBITS[x & 0x07])
  92. #define WHICHTRIPLE(n,x)  ((n == 0)? TRIPLEFIRST(x) : \
  93.                             ((n == 1)? TRIPLESECOND(x) : TRIPLETHIRD(x)))
  94.  
  95. #define QUADFIRST(x)    DOUBLEFIRST(DOUBLEFIRST(x))
  96. #define QUADSECOND(x)   DOUBLESECOND(DOUBLEFIRST(x))
  97. #define QUADTHIRD(x)    DOUBLEFIRST(DOUBLESECOND(x))
  98. #define QUADFORTH(x)    DOUBLESECOND(DOUBLESECOND(x))
  99. #define WHICHQUAD(n,x)  ((n == 0)? QUADFIRST(x) : \
  100.                           ((n == 1)? QUADSECOND(x) : \
  101.                             ((n == 2)? QUADTHIRD(x) : QUADFORTH(x))))
  102.  
  103. #define WHICHBITS(m,r,x)  ((m <= EMUNORMAL)? WHICHNORMAL(r,x) : \
  104.                             ((m == EMUHALF)? WHICHDOUBLE(r,x) : \
  105.                               ((m == EMUTRIPLE)? WHICHTRIPLE(r,x) : \
  106.                                 WHICHQUAD(r,x))))
  107.  
  108. extern int drucke( char *memory,
  109.                    long offset, long width, long height,
  110.                    long hdpi, long vdpi, int flag,
  111.                    int landscape, const char *options );
  112.  
  113. #ifdef LANDSCAPE
  114. extern int druck_landscape( char *memory,
  115.                             long xoffset, long yoffset,
  116.                             long width, long height,
  117.                             PAGESIZE *pg,
  118.                             PRTHMODE *phm, PRTVMODE *pvm,
  119.                             boolean onlypart );
  120. #endif
  121.  
  122. #ifdef PORTRAIT
  123. extern int druck_portrait( char *memory,
  124.                            long xoffset, long yoffset,
  125.                            long width, long height,
  126.                            PAGESIZE *pg,
  127.                            PRTHMODE *phm, PRTVMODE *pvm,
  128.                            boolean onlypart );
  129. #endif
  130.  
  131. extern int workoptions( const char *optionen,
  132.                         long *offset, long *width, long *height,
  133.                         long *hdpi, long *vdpi, int *landscape );
  134.  
  135. int main( int argc, const char *argv[] ) {
  136.   const char *shm_name, *optionen;
  137.   char  *memory;
  138.   long  i, shm, offset, w, h, xdpi, ydpi;
  139.   int   landscape, ret, flag;
  140.  
  141.   if ( argc < 6 ) {
  142.     Cconws( "Zuwenig Argumente!\r\n" );
  143.     Cconws( "Richtig: shared_mem_file -Offset -pl weite hoehe hdpi vdpi [file] [-\"Optionen]\r\n" );
  144.     Cconws( "-pl: p = 1: nur ein Teil, sonst: mehrere Teile\r\n" );
  145.     Cconws( "     l = l: landscape, sonst: portrait\r\n" );
  146.     return -1;
  147.   }
  148.  
  149.   Psignal( SIGUSR1, (long)SIG_IGN );
  150.  
  151.   /* Diese Routine mit Parameter versehen! */
  152.   /* Es wird mit Shared Memory gearbeitet */
  153.   /* Wenn der erste Buchstabe eine Zahl ist, */
  154.   /* dann wird diese als Adresse angenommen */
  155.   shm_name = argv[1];
  156.   if( isdigit( *shm_name ) ) {
  157.     if ( ( i = atol( shm_name ) ) <= 0 )
  158.       return -ENOENT;
  159.     memory = (char *)i;
  160.     shm_name = NULL;
  161.   } else  {
  162.     if ( ( shm = Fopen( shm_name, O_RDONLY ) ) < 0 )
  163.       return (int)shm;
  164.     else if ( ( i = Fcntl( (int)shm, 0L, SHMGETBLK ) ) < 0 )
  165.       return (int)i;  /* Fehler melden */
  166.     memory = (char *)i;
  167.   }
  168.  
  169.   /* Es folgt das Offset */
  170.   offset = -atol( argv[2] );  /* bisheriges offset */
  171.   flag = 2; /* Inhalt */
  172.   if(  argv[3][1] == '1'  )
  173.     flag |= 4;
  174.   if(  offset==0  )
  175.     flag |= 1;
  176.   landscape = ( argv[3][2] == 'l' );
  177.  
  178.   w = atol( argv[4] );
  179.   h = atol( argv[5] );
  180.   xdpi = atol( argv[6] );
  181.   ydpi = atol( argv[7] );
  182.  
  183.   optionen = NULL;
  184.   if ( argc > 8 ) {
  185.     if(  argv[8][0]=='-'  &&  argv[8][1]=='\"'  ) {
  186.       optionen = argv[8]+2;
  187.       if ( ( ret = prt_open( NULL ) ) != 0 )
  188.         return ret;
  189.     } else {
  190.       if ( ( ret = prt_open( argv[8] ) ) != 0 )
  191.         return ret;
  192.       optionen = argv[9]+2;
  193.     }
  194.   } else if ( ( ret = prt_open( NULL ) ) != 0 )
  195.     return ret;
  196.  
  197.   if ( ( ret = workoptions( optionen, &offset, &w, &h, &xdpi, &ydpi, &landscape ) ) == 0 ) {
  198.  
  199.     if(  (long)memory==1L  )
  200.       ret = drucke( (char *)0L, 0, 0, 0, 0, 0, 4, landscape, optionen );  /* Nur Ende */
  201.     else
  202.       ret = drucke( memory, offset, w, h, xdpi, ydpi, flag, landscape, optionen );
  203.  
  204.   }
  205.  
  206.   if( shm_name ) {
  207.     Fclose( (int)shm ); /* Shared-Memory-Datei freigeben */
  208.     shm = -1L;
  209.     Mfree( memory );  /* Speicher freigeben */
  210.     Fdelete( shm_name );
  211.   }
  212.  
  213.   if ( ret ) {
  214.     Cconws( "Treiberfehler!\r\n" );
  215.     ret = -1;
  216.   } else
  217.     ret = prt_close();
  218.  
  219.   return ret;
  220. }
  221.  
  222. PAGESIZE *PAGE_getsize( long width, long height, int landscape ) {
  223.   long i, ret;
  224. #if ( PAGEsizes < 1 )
  225. # error "You have to define at least one PAGEsize!"
  226. #endif
  227. #ifndef LANDSCAPE
  228.   if ( landscape ) {
  229.     Cconws( "Dieser Treiber beherrscht kein landscape!\r\n" );
  230.     return NULL;
  231.   }
  232. #endif
  233. #ifndef PORTRAIT
  234.   if ( !landscape ) {
  235.     Cconws( "Dieser Treiber beherrscht kein portrait!\r\n" );
  236.     return NULL;
  237.   }
  238. #endif
  239.   if ( width > MAXSIZE )
  240.     width = MAXSIZE;
  241.   if ( height > MAXSIZE )
  242.     height = MAXSIZE;
  243.  
  244.   /* Optimalen Eintrag finden */
  245.   for ( i = 0, ret = -1; ret == -1 && i < PAGEsizes; i++ )
  246.     if ( width  >= PAGEsize[i].p_minwidth &&
  247.          width  <= PAGEsize[i].p_maxwidth &&
  248.          height >= PAGEsize[i].p_minheight &&
  249.          height <= PAGEsize[i].p_maxheight &&
  250.          PAGEsize[i].p_landscape == landscape )
  251.       ret = i;
  252.  
  253.   /* Irgendeinen Eintrag finden */
  254.   for ( i = PAGEsizes-1; ret == -1 && i >= 0; i-- )
  255.     if ( PAGEsize[i].p_landscape == landscape )
  256.       ret = i;
  257.  
  258.   /* Noteintrag verwenden */
  259.   if ( ret == -1 )
  260.     ret = PAGEsizes-1;
  261.  
  262.   return PAGEsize+ret;
  263. }
  264.  
  265. #define abs(x) ((x<0)?-x:x)
  266.  
  267. PRTVMODE *PRT_getvmode( long dpi ) {
  268.   long i, ret, rdiff, diff;
  269. #if ( PRTvmodes < 1 )
  270. # error "You have to define at least one PRTvmode!"
  271. #endif
  272.   for ( ret = 0, rdiff = PRTvmode[ret].p_dpi - dpi, i = 1;
  273.         rdiff && i < PRTvmodes;
  274.         i++ ) {
  275.     diff = PRTvmode[i].p_dpi - dpi;
  276.     if ( abs(diff) < abs(rdiff) ) {
  277.       rdiff = diff;
  278.       ret = i;
  279.     } else if ( abs(diff) == abs(rdiff) && diff > 0 ) {
  280.       rdiff = diff;
  281.       ret = i;
  282.     }
  283.   }
  284.   return PRTvmode+ret;
  285. }
  286.  
  287. PRTHMODE *PRT_gethmode( long dpi ) {
  288.   long i, ret, rdiff, diff;
  289. #if ( PRThmodes < 1 )
  290. # error "You have to define at least one PRThmode!"
  291. #endif
  292.   for ( ret = 0, rdiff = PRThmode[ret].p_dpi - dpi, i = 1;
  293.         rdiff && i < PRThmodes;
  294.         i++ ) {
  295.     diff = PRThmode[i].p_dpi - dpi;
  296.     if ( abs(diff) < abs(rdiff) ) {
  297.       rdiff = diff;
  298.       ret = i;
  299.     } else if ( abs(diff) == abs(rdiff) && diff > 0 ) {
  300.       rdiff = diff;
  301.       ret = i;
  302.     }
  303.   }
  304.   return PRThmode+ret;
  305. }
  306.  
  307. #pragma warn -par
  308. int drucke( char *memory,
  309.             long offset, long width, long height,
  310.             long hdpi, long vdpi, int flag,
  311.             int landscape, const char *options ) {
  312.   int ret = 0;
  313.   long xoffset = 0, yoffset = 0;
  314.   PAGESIZE *pg = NULL;
  315.   PRTVMODE *pvm = NULL;
  316.   PRTHMODE *phm = NULL;
  317.   if ( landscape )
  318.     xoffset = offset;
  319.   else
  320.     yoffset = offset;
  321.   if ( xoffset + width && yoffset + height ) {
  322.     if ( ( pg = PAGE_getsize( +(1000*(xoffset+width))/hdpi, +(1000*(yoffset+height))/vdpi, landscape ) ) == NULL )
  323.       return -1;
  324.     if ( pg->p_landscape ) {
  325.       pvm = PRT_getvmode( hdpi );
  326.       phm = PRT_gethmode( vdpi );
  327.     } else {
  328.       pvm = PRT_getvmode( vdpi );
  329.       phm = PRT_gethmode( hdpi );
  330.     }
  331.   }
  332.   if ( width <= 0 && height <= 0 )
  333.     flag &= ~2;
  334.   if ( flag & 1 ) { /* Anfang? */
  335.     /* Drucker initialisieren */
  336.     prt_block( PRTinit+1, *PRTinit );
  337.     if ( pvm && pvm->p_initplus )
  338.       prt_block( pvm->p_initplus+1, *pvm->p_initplus );
  339.     if ( phm && phm->p_initplus )
  340.       prt_block( phm->p_initplus+1, *phm->p_initplus );
  341.   }
  342.   if ( flag & 2 ) { /* Daten? */
  343. #if defined( LANDSCAPE ) && defined( PORTRAIT )
  344.     if ( pg->p_landscape )
  345.       ret = druck_landscape( memory, xoffset, yoffset, width, height, pg, phm, pvm, !(flag & 4) );
  346.     else
  347.       ret = druck_portrait( memory, xoffset, yoffset, width, height, pg, phm, pvm, !(flag & 4) );
  348. #elif defined( LANDSCAPE )
  349.     ret = druck_landscape( memory, xoffset, yoffset, width, height, pg, phm, pvm, !(flag & 4) );
  350. #else
  351.     ret = druck_portrait( memory, xoffset, yoffset, width, height, pg, phm, pvm, !(flag & 4) );
  352. #endif
  353.   }
  354.   if ( flag & 4 ) { /* Ende? */
  355.     /* Drucker zurücksetzen */
  356.     if ( pvm && pvm->p_resetplus )
  357.       prt_block( pvm->p_resetplus+1, *pvm->p_resetplus );
  358.     if ( phm && phm->p_resetplus )
  359.       prt_block( phm->p_resetplus+1, *phm->p_resetplus );
  360.     prt_block( PRTreset+1, *PRTreset );
  361.   }
  362.   return ret;
  363. }
  364.  
  365. #pragma warn -par
  366. /*
  367.     Zusätzliche Optionen abarbeiten
  368.     <--- 0: Ok.
  369. */
  370. int workoptions( const char *optionen,
  371.                  long *offset, long *width, long *height,
  372.                  long *hdpi, long *vdpi, int *landscape ) {
  373.   return 0;
  374. }
  375. #pragma warn .par
  376.  
  377. #define PIXELTOBYTE(x)      x += 7; x >>= 3
  378. #define BYTESOFPIXEL(x)     ( ( x + 7 ) >> 3 )
  379. #define PIXELTOEVENBYTE(x)  x += 15; x >>= 4; x += x
  380. #define EVENBYTESOFPIXEL(x) ( ( ( x + 15 ) >> 4 ) * 2 )
  381.  
  382. #ifdef LANDSCAPE
  383. int druck_landscape( char *memory,
  384.                      long xoffset, long yoffset,
  385.                      long width, long height,
  386.                      PAGESIZE *pg, PRTHMODE *phm, PRTVMODE *pvm,
  387.                      boolean onlypart ) {
  388.   int ret = 0;
  389.   int p_width, p_height;
  390. #define P_LEFT    pvm->p_top
  391. #define P_RIGHT   pvm->p_bottom
  392. #define P_TOP     phm->p_right
  393. #define P_BOTTOM  phm->p_left
  394.   char *buffer;
  395.   int startvskip, starthskip, hmultiplier, vmultiplier;
  396.   int vskip;
  397.  
  398.   int b, line, hrun, m, vrun, hskip, white, l;
  399.   char *srs, *dst;
  400.   boolean needlesplit = (phm->p_mode == NEEDLESPLIT);
  401.   boolean outputdone;
  402.  
  403.   if ( yoffset != 0 ) {
  404.     Cconws( "Im landscape-Modus die Seiten von links nach rechts aufbauen lassen!\r\n" );
  405.     return -1;
  406.   }
  407.  
  408.   /*
  409.       Vorberechnungen
  410.   */
  411.   if ( phm->p_mode < 1 )
  412.     hmultiplier = 1;
  413.   else
  414.     hmultiplier = phm->p_mode;
  415.  
  416.   if ( pvm->p_mode < 0 )
  417. #ifdef EMUHALFPOINTBYOR
  418.     vmultiplier = (pvm->p_mode == HALFPOINT) + 1;
  419. #else
  420.     vmultiplier = (pvm->p_mode < 0) + 1;
  421. #endif
  422.   else if ( pvm->p_mode == 0 )
  423.     vmultiplier = 1;
  424.   else if ( pvm->p_mode > EMUMAX )
  425.     vmultiplier = EMUMAX;
  426.   else
  427.     vmultiplier = pvm->p_mode;
  428.  
  429. #if defined(NONEEDLESPLITATEMUHALFPOINT) && !defined(EMUHALFPOINTBYOR)
  430.   needlesplit &= pvm->p_mode != EMUHALFPOINT;
  431. #endif
  432.  
  433.   PIXELTOEVENBYTE( width ); /* In gerade Anzahl an Byte umrechnen */
  434.  
  435.   p_width = (int)(+(pg->p_width * pvm->p_dpi) / 1000);
  436.   p_width -= P_RIGHT; /* ohne unbedruckbaren rechter Rand */
  437.   p_width -= (int)xoffset;  /* ohne bereits gedruckten Teil */
  438.   PIXELTOBYTE( p_width ); /* In Anzahl Byte umrechnen */
  439.   if ( (long)p_width > width )  /* maximal den zu druckenden Teil beachten */
  440.     p_width = (int)width;
  441.  
  442.   /* unbedruckbaren linken Rand entfernen */
  443.   if ( (long)P_LEFT > xoffset ) { /* beim streifenweisen drucken u.U. kein unbedruckbarer Bereich */
  444.     starthskip = P_LEFT - (int)xoffset;
  445.     PIXELTOBYTE( starthskip );
  446.     memory += starthskip;
  447.     p_width -= starthskip;
  448.     starthskip <<= 3; /* Soviele Pixelzeilen am Anfang jeweils vorfahren */
  449.     starthskip -= P_LEFT;
  450.     starthskip += (int)xoffset;
  451.   } else
  452.     starthskip = 0;
  453.  
  454.   p_height = (int)(+(pg->p_height * phm->p_dpi) / 1000);
  455.   p_height -= P_BOTTOM; /* ohne unbedruckbaren unteren Rand */
  456.   if ( (long)p_height > height ) {  /* maximal den zu druckenden Teil beachten */
  457.     startvskip = p_height - (int)height;  /* Pixelvorschub an Anfang jeder Zeile */
  458.     p_height = (int)height;
  459.   } else
  460.     startvskip = 0;
  461.   /* unbeduckbaren oberen Rand entfernen */
  462.   memory += P_TOP * width;
  463.   p_height -= P_TOP;
  464.  
  465.   p_height--; /* reine Handlingfrage */
  466.  
  467.   /* unbedruckten oberen Rand entfernen */
  468.   while ( p_height >= 0 &&
  469.           prt_whitebytes( memory, p_width ) == p_width ) {
  470.     memory += width;
  471.     p_height--;
  472.   }
  473.   /* unbedruckten unteren Rand entfernen */
  474.   for ( srs = memory + p_height * width;
  475.         p_height >= 0 && prt_whitebytes( srs, p_width ) == p_width;
  476.         p_height--, srs -= width, startvskip++ );
  477.  
  478.   /* unbedruckten linken Rand entfernen */
  479.   for ( srs = memory, b = (int)prt_whitebytes( srs, p_width ), line = 0;
  480.         line <= p_height && b > 0;
  481.         line++, srs += width, b =(int)prt_whitebytes( srs, b ) );
  482.   if ( b > 0 ) {
  483.     memory += b;
  484.     starthskip += b << 3;
  485.     p_width -= b;
  486.   }
  487.   /* unbedruckten rechten Rand entfernen */
  488.   for ( srs = memory+p_width-1, b = p_width, line = 0;
  489.         line <= p_height && b > 0;
  490.         line++, srs += width ) {
  491.     for ( m = 0; m < p_width && !srs[-m]; m++ );
  492.     if ( m < b )
  493.       b = m;
  494.   }
  495.   if ( b > 0 )
  496.     p_width -= b;
  497.  
  498.   /* Ausgabezwischenspeicher anfordern */
  499.   if ( ( buffer = malloc( (p_height+1) * phm->p_bppl * hmultiplier ) ) == NULL ) {
  500.     Cconws( "Nicht genug Speicher für den Zeilenpuffer!\r\n" );
  501.     return -1;
  502.   }
  503.  
  504.   /*
  505.       Druck-Initialisierung
  506.   */
  507.   hskip = starthskip;
  508.   if ( pvm->p_mode > EMUNORMAL )
  509.     hskip *= vmultiplier;
  510.  
  511.   /*
  512.       Hauptausgabeschleife
  513.   */
  514.   for ( ;
  515.         p_width > 0;
  516.         memory += (pvm->p_mode < 0)? phm->p_bppl*2 : phm->p_bppl,
  517.           p_width -= (pvm->p_mode < 0)? phm->p_bppl*2 : phm->p_bppl ) {
  518.     for ( vrun = vmultiplier-1; vrun >= 0; vrun-- ) {
  519.       for ( hrun = needlesplit? 1 : 0; hrun >= 0; hrun-- ) {
  520.         vskip = startvskip;
  521.         for ( srs = memory + p_height * width, line = 0, dst = buffer;
  522.               line <= p_height;
  523.               srs -= width, line++ ) {
  524.           for ( m = hmultiplier; m > 0; m-- ) {
  525.             if ( needlesplit && (line & 1) == hrun )
  526.               for ( b = 0; b < phm->p_bppl; b++ )
  527.                 *dst++ = 0;
  528.             else if ( pvm->p_mode < 0 ) {
  529.               if ( phm->p_bppl * 2 <= p_width ) {
  530.                 for ( b = 0; b < phm->p_bppl*2; b += 2 )
  531.                   if ( vrun )
  532.                     *dst++ = (EVENBITS(srs[b]) << 4) | EVENBITS(srs[b+1]);
  533. #ifdef EMUHALFPOINTBYOR
  534.                   else if ( pvm->p_mode == EMUHALFPOINT )
  535.                     *dst++ = ((EVENBITS(srs[b]) | ODDBITS(srs[b])) << 4) |
  536.                              EVENBITS(srs[b+1]) | ODDBITS(srs[b+1]);
  537. #endif
  538.                   else
  539.                     *dst++ = (ODDBITS(srs[b]) << 4) | ODDBITS(srs[b+1]);
  540.               } else {
  541.                 for ( b = 0; b < p_width; b++ ) {
  542.                   if ( b & 1 )
  543.                     if ( vrun )
  544.                       *dst++ |= EVENBITS(srs[b]);
  545. #ifdef EMUHALFPOINTBYOR
  546.                     else if ( pvm->p_mode == EMUHALFPOINT )
  547.                       *dst++ |= EVENBITS(srs[b]) | ODDBITS(srs[b]);
  548. #endif
  549.                     else
  550.                       *dst++ |= ODDBITS(srs[b]);
  551.                   else if ( vrun )
  552.                     *dst = EVENBITS(srs[b]) << 4;
  553. #ifdef EMUHALFPOINTBYOR
  554.                   else if ( pvm->p_mode == EMUHALFPOINT )
  555.                     *dst = (EVENBITS(srs[b]) | ODDBITS(srs[b])) << 4;
  556. #endif
  557.                   else
  558.                     *dst = ODDBITS(srs[b]) << 4;
  559.                 }
  560.                 if ( b & 1 ) {
  561.                   b++;
  562.                   dst++;
  563.                 }
  564.                 for ( ; b < phm->p_bppl*2; b += 2 )
  565.                   *dst++ = '\0';
  566.               }
  567.             } else if ( vmultiplier > EMUNORMAL ) {
  568.               int n, nmp;
  569.               n = vmultiplier-vrun-1;
  570.               nmp = n * phm->p_bppl;
  571.               if ( (nmp + phm->p_bppl)/vmultiplier <= p_width ) {
  572.                 for ( b = 0; b < phm->p_bppl; b++ )
  573.                   *dst++ = WHICHBITS( vmultiplier, (n + b) % vmultiplier, srs[(nmp + b) / vmultiplier] );
  574.               } else {
  575.                 for ( b = 0; (nmp + b)/vmultiplier < p_width; b++ )
  576.                   *dst++ = WHICHBITS( vmultiplier, (n + b) % vmultiplier, srs[(nmp + b) / vmultiplier] );
  577.                 for ( ; b < phm->p_bppl; b++ )
  578.                   *dst++ = '\0';
  579.               }
  580.             } else if ( phm->p_bppl <= p_width ) {
  581.               for ( b = 0; b < phm->p_bppl; b++ )
  582.                 *dst++ = srs[b];
  583.             } else {
  584.               for ( b = 0; b < p_width; b++ )
  585.                 *dst++ = srs[b];
  586.               for ( ; b < phm->p_bppl; b++ )
  587.                 *dst++ = '\0';
  588.             }
  589.           }
  590.         }
  591.  
  592.         for ( srs = buffer,
  593.                 line *= hmultiplier, vskip *= hmultiplier,
  594.                 outputdone = false;
  595.               line > 0;
  596.               ) {
  597.           white = (int)prt_whitebytes( srs, line * phm->p_bppl );
  598.           white /= phm->p_bppl;
  599.           srs += white * phm->p_bppl;
  600.           vskip += white;
  601.           line -= white;
  602.  
  603.           if ( line > 0 ) {
  604.             outputdone = true;
  605.             if ( hskip > 1 || hskip == 1 && pvm->p_mode != EMUHALFPOINT ) {
  606.               b = 0;
  607.               if ( pvm->p_mode == EMUHALFPOINT ) {
  608.                 b = hskip & 1;
  609.                 hskip /= 2;
  610.               }
  611.               while ( hskip > 255 ) {
  612.                 prt_block( pvm->p_vskip+1, pvm->p_vskip[0] );
  613.                 prt_byte( 255 );
  614.                 hskip -= 255;
  615.               }
  616.               if ( hskip ) {
  617.                 prt_block( pvm->p_vskip+1, pvm->p_vskip[0] );
  618.                 prt_byte( hskip );
  619.               }
  620.               hskip = b;
  621.             }
  622.             if ( vskip >= phm->p_relposmin ) {
  623.               b = vskip;
  624.               b *= phm->p_relposfac;
  625.               b /= phm->p_relposdiv;
  626.               if ( b ) {
  627.                 prt_block( phm->p_relpos+1, phm->p_relpos[0] );
  628.                 prt_byte( b );
  629.                 prt_byte( b >> 8 );
  630.                 b *= phm->p_relposdiv;
  631.                 b /= phm->p_relposfac;
  632.                 vskip -= b;
  633.               }
  634.             }
  635.             for ( l = 0;
  636.                   l < line &&
  637.                     prt_whitebytes( srs + l * phm->p_bppl, phm->p_relposmin * phm->p_bppl) < phm->p_relposmin * phm->p_bppl;
  638.                   l++ );
  639.             prt_block( phm->p_graphic+1, phm->p_graphic[0] );
  640.             prt_byte( vskip + l );
  641.             prt_byte( (vskip + l) >> 8 );
  642.             for ( ; vskip > 0; vskip-- )
  643.               for ( b = phm->p_bppl; b > 0; b-- )
  644.                 prt_byte( 0 );
  645.             prt_block( srs, l * phm->p_bppl );
  646.             line -= l;
  647.             srs += l * phm->p_bppl;
  648.           }
  649.         }
  650.         if ( outputdone ) {
  651. #if 0
  652.           char bx[14];
  653.           const char *_itoa( int i, char *b, int r );
  654.           prt_block( phm->p_cr+1, phm->p_cr[0] );
  655.           _itoa( p_width, bx, 10 );
  656.           prt_string( bx );
  657. #endif
  658.           prt_block( phm->p_cr+1, phm->p_cr[0] );
  659.         }
  660.       }
  661.       if ( pvm->p_mode < 0 ) {
  662.         if ( vrun & 1 ) {
  663.           if ( pvm->p_mode != EMUHALFPOINT )
  664.             hskip++;
  665.         } else {
  666.           if ( pvm->p_mode != EMUHALFPOINT ) {
  667.             if ( phm->p_bppl * 2 <= p_width )
  668.               hskip += (phm->p_bppl << 4) - 1;
  669.             else
  670.               hskip += (p_width << 3) - 1;
  671.           } else {
  672.             if ( phm->p_bppl * 2 <= p_width )
  673.               hskip += phm->p_bppl << 4;
  674.             else
  675.               hskip += p_width << 3;
  676.           }
  677.         }
  678.       } else if ( phm->p_bppl <= p_width )
  679.         hskip += phm->p_bppl << 3;
  680.       else
  681.         hskip += p_width << 3;
  682.     }
  683.   }
  684.  
  685.   /*
  686.       Ende
  687.   */
  688.   free( buffer ); /* den brauchen wir erstmal nicht mehr */
  689.   if ( onlypart && hskip > 0 ) {
  690.     if ( pvm->p_mode == EMUHALFPOINT )
  691.       hskip /= 2;
  692.     while ( hskip > 255 ) {
  693.       prt_block( pvm->p_vskip+1, pvm->p_vskip[0] );
  694.       prt_byte( 255 );
  695.       hskip -= 255;
  696.     }
  697.     if ( hskip ) {
  698.       prt_block( pvm->p_vskip+1, pvm->p_vskip[0] );
  699.       prt_byte( hskip );
  700.     }
  701.   }
  702.  
  703.   return ret;
  704. }
  705. #endif  /* LANDSCAPE */
  706.  
  707. #ifdef PORTRAIT
  708. int druck_portrait( char *memory,
  709.                      long xoffset, long yoffset,
  710.                      long width, long height,
  711.                      PAGESIZE *pg, PRTHMODE *phm, PRTVMODE *pvm,
  712.                      boolean onlypart ) {
  713.   int ret = 0;
  714.   int p_width, p_height;
  715. #undef  P_TOP
  716. #undef  P_BOTTOM
  717. #undef  P_LEFT
  718. #undef  P_RIGHT
  719. #define P_TOP     (pvm->p_top)
  720. #define P_BOTTOM  (pvm->p_bottom)
  721. #define P_LEFT    (phm->p_left)
  722. #define P_RIGHT   (phm->p_right)
  723.   int starthskip, startvskip, hmultiplier, vmultiplier;
  724.  
  725.   int startlinehskip, hskip, vskip, b, line, m, white, column, columns,
  726.       hrun, vrun, srswidth;
  727.   char *buffer, *vbuffer, *srs, *dst;
  728.   boolean outputdone;
  729.   boolean needlesplit = (phm->p_mode == NEEDLESPLIT);
  730.  
  731.   if ( xoffset != 0 ) {
  732.     Cconws( "Im portrait-Modus die Seiten von oben nach unten aufbauen lassen!\r\n" );
  733.     return -1;
  734.   }
  735.  
  736.   /*
  737.       Vorberechnungen
  738.   */
  739.  
  740.   hmultiplier = (phm->p_mode < 1)? 1 : phm->p_mode;
  741. #ifdef EMUHALFPOINTBYOR
  742.   vmultiplier = (pvm->p_mode == HALFPOINT)? 2 :
  743. #else
  744.   vmultiplier = (pvm->p_mode < 0)? 2 :
  745. #endif
  746.                  ((pvm->p_mode < 1)? 1 : pvm->p_mode);
  747. #if defined( NONEEDLESPLITATEMUHALFPOINT ) && !defined( EMUHALFPOINTBYOR )
  748.   needlesplit &= (pvm->p_mode != EMUHALFPOINT);
  749. #endif
  750.  
  751.   PIXELTOEVENBYTE( width );
  752.  
  753.   p_width = (int)(+(pg->p_width * phm->p_dpi) / 1000);
  754.   p_width -= P_RIGHT; /* ohne unbedruckbaren rechter Rand */
  755.   PIXELTOBYTE( p_width ); /* In Anzahl Byte umrechnen */
  756.   if ( (long)p_width > width )  /* maximal den zu druckenden Teil beachten */
  757.     p_width = (int)width;
  758.  
  759.   /* unbedruckbaren linken Rand entfernen */
  760.   if ( P_LEFT > 0 ) {
  761.     starthskip = P_LEFT;
  762.     PIXELTOBYTE( starthskip );
  763.     memory += starthskip;
  764.     p_width -= starthskip;
  765.     starthskip <<= 3; /* Soviele Pixelzeilen am Anfang jeweils vorfahren */
  766.     starthskip -= P_LEFT;
  767.   } else
  768.     starthskip = 0;
  769.  
  770.   p_height = (int)(+(pg->p_height * phm->p_dpi) / 1000);
  771.   p_height -= P_BOTTOM; /* ohne unbedruckbaren unteren Rand */
  772.   if ( (long)p_height > height )  /* maximal den zu druckenden Teil beachten */
  773.     p_height = (int)height;
  774.   /* unbeduckbaren oberen Rand entfernen */
  775.   if ( P_TOP > yoffset ) {
  776.     memory += (P_TOP - yoffset) * width;
  777.     p_height -= (P_TOP - (int)yoffset);
  778.   }
  779.   startvskip = 0;
  780.  
  781.   p_height--; /* reine Handlingfrage */
  782.  
  783.   /* unbedruckten oberen Rand entfernen */
  784.   while ( p_height >= 0 &&
  785.           prt_whitebytes( memory, p_width ) == p_width ) {
  786.     memory += width;
  787.     p_height--;
  788.     startvskip++;
  789.   }
  790.   /* unbedruckten unteren Rand entfernen */
  791.   for ( srs = memory + p_height * width;
  792.         p_height >= 0 && prt_whitebytes( srs, p_width ) == p_width;
  793.         p_height--, srs -= width );
  794.  
  795.   /* unbedruckten linken Rand entfernen */
  796.   for ( srs = memory, b = (int)prt_whitebytes( srs, p_width ), line = 0;
  797.         line < p_height && b > 0;
  798.         line++, srs += width, b =(int)prt_whitebytes( srs, b ) );
  799.   if ( b > 0 ) {
  800.     memory += b;
  801.     starthskip += b << 3;
  802.     p_width -= b;
  803.   }
  804.   /* unbedruckten rechten Rand entfernen */
  805.   for ( srs = memory+p_width-1, b = p_width, line = 0;
  806.         line < p_height && b > 0;
  807.         line++, srs += width ) {
  808.     for ( m = 0; m < p_width && !srs[-m]; m++ );
  809.     if ( m < b )
  810.       b = m;
  811.   }
  812.   if ( b > 0 )
  813.     p_width -= b;
  814.  
  815.   /* Ausgabezwischenspeicher anfordern */
  816.   if ( ( buffer = malloc( (long)(p_width * phm->p_bppl) << 3 ) ) == NULL ) {
  817.     Cconws( "Nicht genug Speicher für den Zeilenpuffer!\r\n" );
  818.     return -1;
  819.   }
  820.   if ( vmultiplier > 1 &&
  821.        ( vbuffer = malloc( (long)(width * phm->p_bppl) << 3 ) ) == NULL ) {
  822.     Cconws( "Nicht genug Speicher für Zeilenzwischenpuffer!\r\n" );
  823.     return -1;
  824.   }
  825.  
  826.   /*
  827.       Druck-Initialisierung
  828.   */
  829.   vskip = startvskip;
  830.   if ( pvm->p_mode > 1 )
  831.     vskip *= pvm->p_mode;
  832.  
  833.   /*
  834.       Hauptschleife
  835.   */
  836.   for ( ;
  837.         p_height >= 0;
  838.         p_height -= phm->p_bppl << ((pvm->p_mode < 0)? 4 : 3),
  839.           memory += width * (phm->p_bppl << ((pvm->p_mode < 0)? 4 : 3)) ) {
  840.     /* weiße Zeilen überspringen */
  841.     for ( ;
  842.           p_height >= 0 &&
  843.             prt_whitebytes( memory, p_width ) == p_width;
  844.           p_height--, memory += width, vskip += ((pvm->p_mode > 1)? pvm->p_mode : 1) );
  845.  
  846.     startlinehskip = starthskip;
  847.  
  848.     if ( vmultiplier == 1 )
  849.       vbuffer = memory;
  850.  
  851. #ifdef EMUHALFPOINTBYOR
  852.     for ( vrun = pvm->p_mode == EMUHALFPOINT,
  853. #else
  854.     for ( vrun = 0,
  855. #endif
  856.             line = 0;
  857.           vrun < vmultiplier;
  858.           vrun++ ) {
  859.  
  860.       if ( vmultiplier > 1 )
  861.         if ( pvm->p_mode == HALFPOINT
  862. #ifndef EMUHALFPOINTBYOR
  863.              || pvm->p_mode == EMUHALFPOINT
  864. #endif
  865.              )
  866.           for ( srs = memory + vrun * width,
  867.                   dst = vbuffer, b = vrun;
  868.                 b < (phm->p_bppl << 4);
  869.                 srs += width*2, dst += width, b += 2 )
  870.             if ( b <= p_height )
  871.               memcpy( dst, srs, p_width );
  872.             else
  873.               memset( dst, 0, p_width );
  874. #ifdef EMUHALFPOINTBYOR
  875.         else if ( pvm->p_mode == EMUHALFPOINT )
  876.           for ( srs = memory, dst = vbuffer, b = 0;
  877.                 b < (phm->p_bppl << 4);
  878.                 srs += width, b++ )
  879.             if ( b & 1 ) {
  880.               if ( b <= p_height )
  881.                 memor( dst, srs, p_width );
  882.               dst += width;
  883.             } else if ( b <= p_height )
  884.               memcpy( dst, srs, p_width );
  885.             else
  886.               memset( dst, 0, p_width );
  887. #endif
  888.         else
  889.           for ( srs = memory + (line / vmultiplier - 1) * width,
  890.                   dst = vbuffer, b = 0;
  891.                 b < (phm->p_bppl << 3);
  892.                 dst += width, b++, line++ ) {
  893.             if ( !(line % vmultiplier) )
  894.               srs += width;
  895.             if ( line / vmultiplier <= p_height )
  896.               memcpy( dst, srs, p_width );
  897.             else {
  898.               b = (phm->p_bppl << 3) - b;
  899.               line += b-1;
  900.               memset( dst, 0, b*width );
  901.               b = (phm->p_bppl << 3)-1;
  902.             }
  903.           }
  904.  
  905.       if ( p_height >= 0 ) {
  906.         if ( pvm->p_mode > 1 && (p_height+1)*pvm->p_mode < (phm->p_bppl << 3) )
  907.           prt_prtcpysome( buffer, vbuffer,
  908.                           (int)width, p_width,
  909.                           phm->p_bppl, (p_height+1)*pvm->p_mode );
  910.         else if ( pvm->p_mode <= 1 && p_height+1 < (phm->p_bppl << 3) )
  911.           prt_prtcpysome( buffer, vbuffer,
  912.                           (int)width, p_width,
  913.                           phm->p_bppl, p_height+1 );
  914.         else
  915.           prt_prtcpy( buffer, vbuffer,
  916.                       (int)width, p_width,
  917.                       phm->p_bppl );
  918.  
  919.         for ( hrun = (needlesplit != false); hrun >= 0; hrun-- ) {
  920.           hskip = startlinehskip;
  921.           /* Optimierungsschleife */
  922.           for ( srs = buffer, srswidth = (p_width << 3) * phm->p_bppl;
  923.                 srswidth > 0 &&
  924.                   (white = (int)prt_whitebytes( srs, srswidth )) < srswidth;
  925.                 columns *= phm->p_bppl, srs += columns,
  926.                   srswidth -= columns ) {
  927.             white /= phm->p_bppl;
  928.             hskip += white;
  929.             white *= phm->p_bppl;
  930.             srs += white;
  931.             srswidth -= white;
  932.             /* Zuerst der vertikale Vorschub */
  933.             if ( vskip > 0 ) {
  934.               if ( pvm->p_mode == EMUHALFPOINT ) {
  935.                 b = vskip & 1;
  936.                 vskip /= 2;
  937.               }
  938.               while ( vskip > 255 ) {
  939.                 prt_block( pvm->p_vskip+1, pvm->p_vskip[0] );
  940.                 prt_byte( 255 );
  941.                 vskip -= 255;
  942.               }
  943.               if ( vskip > 0 ) {
  944.                 prt_block( pvm->p_vskip+1, pvm->p_vskip[0] );
  945.                 prt_byte( vskip );
  946.                 vskip = 0;
  947.               }
  948.               if ( pvm->p_mode == EMUHALFPOINT )
  949.                 vskip = b;
  950.             }
  951.             /* Jetzt der horizontale Vorschub */
  952.             if ( hskip > phm->p_relposmin ) {
  953.               b = hskip;
  954.               b *= phm->p_relposfac;
  955.               b /= phm->p_relposdiv;
  956.               prt_block( phm->p_relpos+1, phm->p_relpos[0] );
  957.               prt_byte( b );
  958.               prt_byte( b >> 8 );
  959.               b *= phm->p_relposdiv;
  960.               b /= phm->p_relposfac;
  961.               hskip -= b;
  962.             }
  963.             for ( columns = 0;
  964.                   columns < srswidth &&
  965.                     prt_whitebytes( srs+columns, phm->p_bppl*phm->p_relposmin ) != phm->p_bppl*phm->p_relposmin;
  966.                   columns += phm->p_bppl );
  967.             columns /= phm->p_bppl;
  968.             prt_block( phm->p_graphic+1, phm->p_graphic[0] );
  969.             prt_byte( (hskip + columns) * hmultiplier );
  970.             prt_byte( ((hskip + columns) * hmultiplier ) >> 8 );
  971.             for ( ; hskip > 0; hskip-- )
  972.               for ( b = phm->p_bppl * hmultiplier; b > 0; b-- )
  973.                 prt_byte( 0 );
  974.             if ( needlesplit ) {
  975.               for ( dst = srs, column = columns;
  976.                     column > 0;
  977.                     dst += phm->p_bppl, column-- )
  978.                 if ( (column & 1) == hrun )
  979.                   for ( b = 0; b < phm->p_bppl; b++ )
  980.                     prt_byte( 0 );
  981.                 else
  982.                   prt_block( dst, phm->p_bppl );
  983.             } else if ( hmultiplier > 1 ) {
  984.               for ( dst = srs, column = columns;
  985.                     column > 0;
  986.                     dst += phm->p_bppl, column-- )
  987.                 for ( hrun = 0; hrun < hmultiplier; hrun++ )
  988.                   prt_block( dst, phm->p_bppl );
  989.             } else
  990.               prt_block( srs, columns * phm->p_bppl );
  991.             outputdone = true;
  992.           }
  993.           if ( outputdone )
  994.             prt_block( phm->p_cr+1, phm->p_cr[0] );
  995.         }
  996.         if ( pvm->p_mode < 0 )
  997.           if ( !vrun )
  998.             vskip++;
  999.           else if ( (p_height+1) < (phm->p_bppl << 4) - 1 )
  1000.             vskip += p_height;
  1001.           else
  1002.             vskip += (phm->p_bppl << 4) - 1;
  1003.         else if ( pvm->p_mode > 1 && (p_height+1)*pvm->p_mode < (phm->p_bppl << 3) )
  1004.           vskip += (p_height+1) * pvm->p_mode;
  1005.         else if ( pvm->p_mode <= 1 && (p_height+1) < (phm->p_bppl << 3) )
  1006.           vskip += p_height + 1;
  1007.         else
  1008.           vskip += phm->p_bppl << 3;
  1009.       }
  1010.     }
  1011.   }
  1012.  
  1013.   /*
  1014.       Ende
  1015.   */
  1016.   if ( vskip > 0 ) {
  1017.     if ( onlypart ) {
  1018.       if ( pvm->p_mode == EMUHALFPOINT ) {
  1019.         b = vskip & 1;
  1020.         vskip /= 2;
  1021.       }
  1022.       while ( vskip > 255 ) {
  1023.         prt_block( pvm->p_vskip+1, pvm->p_vskip[0] );
  1024.         prt_byte( 255 );
  1025.         vskip -= 255;
  1026.       }
  1027.       if ( vskip > 0 ) {
  1028.         prt_block( pvm->p_vskip+1, pvm->p_vskip[0] );
  1029.         prt_byte( vskip );
  1030.         vskip = 0;
  1031.       }
  1032.       if ( pvm->p_mode == EMUHALFPOINT )
  1033.         vskip = b;
  1034.     }
  1035.   }
  1036.  
  1037.   return ret;
  1038. }
  1039. #endif  /* PORTRAIT */
  1040.  
  1041. #endif  /* NADEL_C */